import java.awt.Canvas;
import java.awt.Color;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

import com.dinim.graphics.GraphicsContextSwingImpl;
import com.dinim.graphics.IGraphicsContext;
import com.dinim.math.GeometryUtil;
import com.dinim.math.TrigonometryUtil;
import com.dinim.matrix.twodimensional.IPoint2D;
import com.dinim.object.Line2D;
import com.dinim.object.Object2D;
import com.dinim.object.Rectangle2D;
import com.dinim.object.Star2D;
import com.dinim.physics2D.IBoundingBox2D;


public class ObjekteUndWinkel {

    static double direction = 0.4;
    static boolean run = true;
    
    public static void main(String[] args) throws InterruptedException, IOException {
        JFrame f = new JFrame();
        f.setSize(500, 500);
        f.setDefaultCloseOperation(f.EXIT_ON_CLOSE);
        
        
        Canvas canvas = new Canvas();
        
        
        f.add(canvas);
        f.setVisible(true);
        
        f.addKeyListener(new KeyListener(){

            public void keyPressed(KeyEvent e) {
                if(e.getKeyText(e.getKeyCode()).equals("Links")){
                    direction = -0.4;
                    run = true;
                }
                if(e.getKeyText(e.getKeyCode()).equals("Rechts")){
                    direction = 0.4;
                    run = true;
                }
                if(e.getKeyText(e.getKeyCode()).equals("Oben")){
                    direction = direction + 0.09;
                    run = true;
                }
                if(e.getKeyText(e.getKeyCode()).equals("Unten")){
                    direction = direction - 0.09;
                    run = true;
                }
            }

            public void keyReleased(KeyEvent e) {
                run = false;
            }

            public void keyTyped(KeyEvent e) {
            }
            
        });
        
        canvas.createBufferStrategy(2);
        BufferStrategy doublebuffer = canvas.getBufferStrategy();
        
        Object2D obj1 = new Star2D(50, 70, 100, 200, 6);
        Object2D obj2 = new Rectangle2D(300, 70, 200, 100);
        
        File imagefile = new File("D:\\Data\\t343490\\Blue hills.jpg");
        
        BufferedImage img = ImageIO.read(imagefile);
        
        
        while(true){
            while(run){
                
                IGraphicsContext gc = new GraphicsContextSwingImpl(doublebuffer.getDrawGraphics());
                gc.setAntialiasing(true);
    
                gc.setColor(Color.white);
                gc.drawFilledRectangle(0, 0, canvas.getWidth(), canvas.getHeight());
                gc.setColor(Color.black);
                obj1.rotate(2*direction, obj1.getCenterPoint());
                obj2.rotate(-1*direction, obj2.getCenterPoint());
                obj1.draw(gc);
                obj2.draw(gc);
//                obj1.drawNormals(gc);
//                obj2.drawNormals(gc);
                List gradientsObj1 = obj1.getNormalGradients();
                System.out.println();
                for(int i = 0; i < gradientsObj1.size(); i++){
                    System.out.println(gradientsObj1.get(i));
                }
                
                /**
                 * Verbindungslinie zwischen Objekten Holen
                 */
                Line2D line = new Line2D(obj1.getCenterPoint(), obj2.getCenterPoint());
    
                double angle = TrigonometryUtil.getAngleWithAdjacentLeg(line.getPoints()[0].getX() - line.getPoints()[1].getX(), 
                                                         GeometryUtil.getLength(line.getPoints()[0].getX(), 
                                                                                line.getPoints()[0].getY(),
                                                                                line.getPoints()[1].getX(), 
                                                                                line.getPoints()[1].getY()));
                
                line.rotate(angle, line.getCenterPoint());
                obj1.rotate(angle, line.getCenterPoint());
                obj2.rotate(angle, line.getCenterPoint());
    
    //            obj1.draw(gc);
    //            obj2.draw(gc);
                
                /**
                 * Punkte Sortieren
                 */
                IPoint2D[] points1 = obj1.getPoints();
                IPoint2D[] points2 = obj2.getPoints();
                ArrayList p1 = new ArrayList();
                ArrayList p2 = new ArrayList();
                for(int i = 0; i < points1.length; i++){
                    p1.add(points1[i]);
                }
                for(int i = 0; i < points2.length; i++){
                    p2.add(points2[i]);
                }
                Comparator comp = new Comparator(){
                    public int compare(Object o1, Object o2) {
                        IPoint2D obj1 = (IPoint2D)o1;
                        IPoint2D obj2 = (IPoint2D)o2;
                        double top1 = obj1.getX();
                        double top2 = obj2.getX();
                        int value = (int)Math.round(top2 - top1);
                        return value;
                    }
                    
                };
                Collections.sort(p1, comp);
                comp = new Comparator(){
    
                    public int compare(Object o1, Object o2) {
                        IPoint2D obj1 = (IPoint2D)o1;
                        IPoint2D obj2 = (IPoint2D)o2;
                        double top1 = obj1.getX();
                        double top2 = obj2.getX();
                        int value = (int)Math.round(top2 - top1);
                        return value;
                    }
                    
                };
                Collections.sort(p2, comp);
    
                /**
                 * Die vordersten Punkte definieren
                 */
                IPoint2D obj1p1 = (IPoint2D)p1.get(p1.size()-1);
                IPoint2D obj1p2 = (IPoint2D)p1.get(p1.size()-2);
                IPoint2D obj2p1 = (IPoint2D)p2.get(0);
                IPoint2D obj2p2 = (IPoint2D)p2.get(1);
    //            gc.drawLine(obj1p1.getX(), obj1p1.getY(), obj2p1.getX(), obj2p1.getY());
    //            gc.drawLine(obj1p1.getX(), obj1p1.getY(), obj2p2.getX(), obj2p2.getY());
    //            gc.drawLine(obj1p2.getX(), obj1p2.getY(), obj2p2.getX(), obj2p2.getY());
    //            gc.drawLine(obj1p2.getX(), obj1p2.getY(), obj2p1.getX(), obj2p1.getY());
                Line2D bestLine1 = new Line2D(obj1p1, obj1p2);
                Line2D bestLine2 = new Line2D(obj2p1, obj2p2);
    //            gc.setColor(Color.red);
    //            bestLine1.draw(gc);
    //            bestLine2.draw(gc);
    //            gc.setColor(Color.black);
                
                
                double bestangle1 = TrigonometryUtil.getAngleWithAdjacentLeg(bestLine1.getPoints()[0].getY() - bestLine1.getPoints()[1].getY(), 
                        GeometryUtil.getLength(bestLine1.getPoints()[0].getX(), 
                                bestLine1.getPoints()[0].getY(),
                                bestLine1.getPoints()[1].getX(), 
                                bestLine1.getPoints()[1].getY()));
                double bestangle2 = TrigonometryUtil.getAngleWithAdjacentLeg(bestLine2.getPoints()[1].getY() - bestLine2.getPoints()[0].getY(), 
                        bestLine2.getLength());
                
                if(bestangle1 >= 90){
                    bestangle1 = bestangle1 + 180;
                }
                if(bestangle2 >= 90){
                    bestangle2 = bestangle2 + 180;
                }
                IPoint2D nearPoint;
                
                
                /**
                 * Objekt 1 drehen!!
                 */
                obj1.rotate(-bestangle1, bestLine1.getCenterPoint());
                obj2.rotate(-bestangle1, bestLine1.getCenterPoint());
    
                if(obj2p1.getX() > obj2p2.getX()){
                    nearPoint = obj2p1;
                }else{
                    nearPoint = obj2p2;
                }
                double diff1 = obj1p1.getX() - nearPoint.getX();
    
                obj1.rotate(bestangle1, bestLine1.getCenterPoint());
                obj2.rotate(bestangle1, bestLine1.getCenterPoint());

                /**
                 * Objekt 2 drehen!!
                 */
                obj1.rotate(-bestangle2, bestLine2.getCenterPoint());
                obj2.rotate(-bestangle2, bestLine2.getCenterPoint());
    
                if(obj1p1.getX() < obj1p2.getX()){
                    nearPoint = obj1p1;
                }else{
                    nearPoint = obj1p2;
                }
                double diff2 = nearPoint.getX() - obj2p1.getX();
    
                obj1.rotate(bestangle2, bestLine2.getCenterPoint());
                obj2.rotate(bestangle2, bestLine2.getCenterPoint());
                
                
                
//                System.out.println();
//                System.out.println("Diff1: " + diff1);
//                System.out.println("Diff2: " + diff2);
                
                
                obj1.rotate(-angle, line.getCenterPoint());
                obj2.rotate(-angle, line.getCenterPoint());
    
                gc.setColor(Color.red);
                bestLine1.draw(gc);
                bestLine2.draw(gc);
                gc.setColor(Color.black);
                
                /**
                 * Vergleichen!!
                 */
                if(diff1 < diff2){
                    gc.drawLine(obj1p1.getX(), obj1p1.getY(), obj2p1.getX(), obj2p1.getY());
                    gc.drawLine(obj1p1.getX(), obj1p1.getY(), obj2p2.getX(), obj2p2.getY());  
                }else{
                    gc.drawLine(obj2p1.getX(), obj2p1.getY(), obj1p1.getX(), obj1p1.getY());
                    gc.drawLine(obj2p1.getX(), obj2p1.getY(), obj1p2.getX(), obj1p2.getY());
                }
                
                
                doublebuffer.show();
    
                Thread.sleep(3);
            }
            
        }
    }
    
}
